add usb device save/restore in qemu
authorTim Deegan <Tim.Deegan@xensource.com>
Wed, 14 Mar 2007 10:44:56 +0000 (10:44 +0000)
committerTim Deegan <Tim.Deegan@xensource.com>
Wed, 14 Mar 2007 10:44:56 +0000 (10:44 +0000)
Signed-off-by: Zhai Edwin <edwin.zhai@intel.com>
tools/ioemu/hw/usb-hid.c
tools/ioemu/hw/usb-ohci.c
tools/ioemu/hw/usb-uhci.c
tools/ioemu/hw/usb.c
tools/ioemu/hw/usb.h
tools/ioemu/vl.c

index 60849a4ed0b2d4946e0c231a40685af57efe644d..c7af3d65abb3aa8ebd3590321af582a02e0e3ad3 100644 (file)
@@ -517,6 +517,49 @@ static void usb_mouse_handle_destroy(USBDevice *dev)
     qemu_free(s);
 }
 
+void usb_mouse_save(QEMUFile *f, void *opaque)
+{
+    USBMouseState *s = (USBMouseState*)opaque;
+
+    qemu_put_be32s(f, &s->dx);
+    qemu_put_be32s(f, &s->dy);
+    qemu_put_be32s(f, &s->dz);
+    qemu_put_be32s(f, &s->buttons_state);
+    qemu_put_be32s(f, &s->x);
+    qemu_put_be32s(f, &s->y);
+    qemu_put_be32s(f, &s->kind);
+    qemu_put_be32s(f, &s->mouse_grabbed);
+    qemu_put_be32s(f, &s->status_changed);
+
+}
+
+int usb_mouse_load(QEMUFile *f, void *opaque, int version_id)
+{
+    USBMouseState *s = (USBMouseState*)opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_be32s(f, &s->dx);
+    qemu_get_be32s(f, &s->dy);
+    qemu_get_be32s(f, &s->dz);
+    qemu_get_be32s(f, &s->buttons_state);
+    qemu_get_be32s(f, &s->x);
+    qemu_get_be32s(f, &s->y);
+    qemu_get_be32s(f, &s->kind);
+    qemu_get_be32s(f, &s->mouse_grabbed);
+    qemu_get_be32s(f, &s->status_changed);
+
+    if ( s->kind == USB_TABLET) {
+        fprintf(logfile, "usb_mouse_load:add usb_tablet_event.\n");
+        qemu_add_mouse_event_handler(usb_tablet_event, s, 1);
+    } else if ( s->kind == USB_MOUSE) {
+        fprintf(logfile, "usb_mouse_load:add usb_mouse_event.\n");
+        qemu_add_mouse_event_handler(usb_mouse_event, s, 0);
+    }
+}
+
+
 USBDevice *usb_tablet_init(void)
 {
     USBMouseState *s;
@@ -536,6 +579,8 @@ USBDevice *usb_tablet_init(void)
 
     pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
 
+    register_savevm("USB tablet dev", 0, 1, usb_mouse_save, usb_mouse_load, s);
+
     return (USBDevice *)s;
 }
 
@@ -558,5 +603,7 @@ USBDevice *usb_mouse_init(void)
 
     pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
 
+    register_savevm("USB mouse dev", 0, 1, usb_mouse_save, usb_mouse_load, s);
+
     return (USBDevice *)s;
 }
index e87d9da70a04bfdadfbf454b676ed83d944554fd..a56326267621a8b09131b0852b321d78fa41c3a3 100644 (file)
@@ -1186,5 +1186,7 @@ void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn)
         qemu_register_usb_port(&ohci->rhport[i].port, ohci, i, ohci_attach);
     }
 
+    register_savevm("OHCI USB", 0, 1, generic_pci_save, generic_pci_load, ohci);
+
     ohci_reset(ohci);
 }
index 7212c5e82d5bc15d8707b3fb083c639a82c21b70..46cff274cf0f146741e89e634ba39b44d9eeea56 100644 (file)
@@ -658,6 +658,50 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
     register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
 }
 
+void uhci_usb_save(QEMUFile *f, void *opaque)
+{
+    int i;
+    UHCIState *s = (UHCIState*)opaque;
+
+    qemu_put_be16s(f, &s->cmd);
+    qemu_put_be16s(f, &s->status);
+    qemu_put_be16s(f, &s->intr);
+    qemu_put_be16s(f, &s->frnum);
+    qemu_put_be32s(f, &s->fl_base_addr);
+    qemu_put_8s(f, &s->sof_timing);
+    qemu_put_8s(f, &s->status2);
+
+    for(i = 0; i < NB_PORTS; i++) {
+        qemu_put_be16s(f, &s->ports[i].ctrl);
+    }
+
+    qemu_put_timer(f, s->frame_timer);
+}
+
+int uhci_usb_load(QEMUFile *f, void *opaque, int version_id)
+{
+    int i;
+    UHCIState *s = (UHCIState*)opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_be16s(f, &s->cmd);
+    qemu_get_be16s(f, &s->status);
+    qemu_get_be16s(f, &s->intr);
+    qemu_get_be16s(f, &s->frnum);
+    qemu_get_be32s(f, &s->fl_base_addr);
+    qemu_get_8s(f, &s->sof_timing);
+    qemu_get_8s(f, &s->status2);
+
+    for(i = 0; i < NB_PORTS; i++) {
+        qemu_get_be16s(f, &s->ports[i].ctrl);
+    }
+
+    qemu_get_timer(f, s->frame_timer);
+
+}
+
 void usb_uhci_init(PCIBus *bus, int devfn)
 {
     UHCIState *s;
@@ -693,4 +737,8 @@ void usb_uhci_init(PCIBus *bus, int devfn)
        to rely on this.  */
     pci_register_io_region(&s->dev, 4, 0x20, 
                            PCI_ADDRESS_SPACE_IO, uhci_map);
+
+    register_savevm("UHCI_usb_pci", 0, 1, generic_pci_save, generic_pci_load, s);
+
+    register_savevm("UHCI usb controller", 0, 1, uhci_usb_save, uhci_usb_load, s);
 }
index 34aac5fa9b6f85f27e13adf2ff9fe0112a3eb2e5..e4166518b0c5984f50945ee4a513510d3245dabd 100644 (file)
@@ -191,3 +191,43 @@ int set_usb_string(uint8_t *buf, const char *str)
     }
     return q - buf;
 }
+
+void generic_usb_save(QEMUFile* f, void *opaque)
+{
+    USBDevice *s = (USBDevice*)opaque;
+
+    qemu_put_be32s(f, &s->speed);
+    qemu_put_8s(f, &s->addr);
+    qemu_put_be32s(f, &s->state);
+
+    qemu_put_buffer(f, s->setup_buf, 8);
+    qemu_put_buffer(f, s->data_buf, 1024);
+
+    qemu_put_be32s(f, &s->remote_wakeup);
+    qemu_put_be32s(f, &s->setup_state);
+    qemu_put_be32s(f, &s->setup_len);
+    qemu_put_be32s(f, &s->setup_index);
+
+}
+
+int generic_usb_load(QEMUFile* f, void *opaque, int version_id)
+{
+    USBDevice *s = (USBDevice*)opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_be32s(f, &s->speed);
+    qemu_get_8s(f, &s->addr);
+    qemu_get_be32s(f, &s->state);
+
+    qemu_get_buffer(f, s->setup_buf, 8);
+    qemu_get_buffer(f, s->data_buf, 1024);
+
+    qemu_get_be32s(f, &s->remote_wakeup);
+    qemu_get_be32s(f, &s->setup_state);
+    qemu_get_be32s(f, &s->setup_len);
+    qemu_get_be32s(f, &s->setup_index);
+
+    return 0;
+}
index 98fde065697f52e282c9df38c20750a0fe79db7f..9df69f8dc8c412be8f88f9660400d1bcaa6594d9 100644 (file)
@@ -176,3 +176,9 @@ USBDevice *usb_tablet_init(void);
 
 /* usb-msd.c */
 USBDevice *usb_msd_init(const char *filename);
+
+/* usb.c */
+void generic_usb_save(QEMUFile* f, void *opaque);
+int generic_usb_load(QEMUFile* f, void *opaque, int version_id);
+
+
index 0b78fa8650d9f6731fa5149a378679b7cca901bb..6f9219fa403c842f1852800e82ac19f57df72277 100644 (file)
@@ -841,10 +841,22 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
 #ifdef CONFIG_DM
 static void timer_save(QEMUFile *f, void *opaque)
 {
+    /* need timer for save/restoe qemu_timer in usb_uhci */
+    if (cpu_ticks_enabled) {
+        hw_error("cannot save state if virtual timers are running");
+    }
+    qemu_put_be64s(f, &cpu_clock_offset);
 }
 
 static int timer_load(QEMUFile *f, void *opaque, int version_id)
 {
+    if (version_id != 1)
+        return -EINVAL;
+    if (cpu_ticks_enabled) {
+        return -EINVAL;
+    }
+
+    qemu_get_be64s(f, &cpu_clock_offset);
     return 0;
 }
 #else  /* !CONFIG_DM */
@@ -3900,6 +3912,7 @@ static int usb_device_add(const char *devname)
     const char *p;
     USBDevice *dev;
     USBPort *port;
+    char usb_name[256] = "USB ";
 
     if (!free_usb_ports)
         return -1;
@@ -3936,6 +3949,12 @@ static int usb_device_add(const char *devname)
     free_usb_ports = port->next;
     port->next = used_usb_ports;
     used_usb_ports = port;
+
+    pstrcpy(usb_name + strlen(usb_name), 
+            sizeof(usb_name) - strlen(usb_name), 
+            devname);
+    register_savevm(usb_name, 0, 1, generic_usb_save, generic_usb_load, dev);
+    
     usb_attach(port, dev);
     return 0;
 }